// MessageBoxFilter.cpp: implementation of the CMessageBoxFilter class.
//
//////////////////////////////////////////////////////////////////////
/********************************************************************
	created:	2012/05/02
	created:	2:5:2012   16:36
	file base:	MessageBoxFilter
	file ext:	cpp
	author:		wuxiangfei
*********************************************************************/
#include "stdafx.h"
#include "MessageBoxFilter.h"
#include <MMSYSTEM.H>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY( ptr ) if ( ptr ) { delete []ptr, ptr = NULL; }
#endif

//////////////////////////////////////////////////////////////////////////

UINT *CMessageBoxFilter::m_OldMessageBoxA;
UINT *CMessageBoxFilter::m_OldMessageBoxW;
BOOL CMessageBoxFilter::m_bEnable;
CString CMessageBoxFilter::m_strCaptionFilter = _T("");
CString CMessageBoxFilter::m_strTextFilter = _T("");
CMessageBoxFilter *CMessageBoxFilter::m_pMessageBoxFilter = NULL;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMessageBoxFilter::CMessageBoxFilter()
{
	m_bEnable = TRUE;

	CMessageBoxFilter::m_strCaptionFilter = _T("SkinSE");
	CMessageBoxFilter::m_strTextFilter = _T("SkinSE");

	HookFun(MessageBoxA, MyMessageBoxA, (void**)&m_OldMessageBoxA);
	HookFun(MessageBoxW, MyMessageBoxW, (void**)&m_OldMessageBoxW);
}

CMessageBoxFilter::~CMessageBoxFilter()
{
	UnHookFun(MessageBoxA, m_OldMessageBoxA);
	UnHookFun(MessageBoxW, m_OldMessageBoxW);

	SAFE_DELETE_ARRAY(m_OldMessageBoxA);
	SAFE_DELETE_ARRAY(m_OldMessageBoxW);
}

void CMessageBoxFilter::HookFun(void *TargProc, void *NewProc, void **l_OldProc, int nByteScopy/*=5*/)
{
	DWORD dwOldProtect;
	::VirtualProtect((LPVOID)TargProc, nByteScopy, PAGE_EXECUTE_READWRITE, &dwOldProtect);
	
	*l_OldProc = new BYTE[nByteScopy+5];
	memcpy(*l_OldProc, TargProc, nByteScopy);
	
	*((BYTE*)(*l_OldProc) + nByteScopy) = 0xE9;
	*(UINT*)((BYTE*)(*l_OldProc) + nByteScopy + 1) = (UINT)(TargProc) + nByteScopy - ((UINT)((*l_OldProc)) + 5 + nByteScopy);
	
	*(BYTE*)TargProc =(BYTE)0xE9;
	
	*(UINT*)((UINT)TargProc + 1) = (UINT)NewProc - ((UINT)TargProc + 5);
	
	::VirtualProtect((LPVOID)TargProc, nByteScopy, dwOldProtect, 0);
}

void CMessageBoxFilter::UnHookFun(void *TartProc, void *l_SavedFun, UINT Len/*=5*/)
{
	DWORD dwOldProtect;
	::VirtualProtect((LPVOID)TartProc, Len, PAGE_EXECUTE_READWRITE, &dwOldProtect);
	memcpy(TartProc, l_SavedFun, Len);
	::VirtualProtect((LPVOID)TartProc, Len, dwOldProtect, 0);
}

int __stdcall CMessageBoxFilter::MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
	CString strText=lpText, strCaption=lpCaption;
	if (m_bEnable && (0<=strCaption.Find(m_strCaptionFilter)||0<=strText.Find(m_strTextFilter)))
	{
		OutputDebugStr(_T("MessageBoxA Hook,") + strCaption + _T(",") + strText + _T("\n"));
		return 0;
	}
	return ((MYMESSAGEBOXA)m_OldMessageBoxA)(hWnd, lpText, lpCaption, uType);
}

int __stdcall CMessageBoxFilter::MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
	CString strText=lpText, strCaption=lpCaption;
	if (m_bEnable && (0<=strCaption.Find(m_strCaptionFilter)||0<=strText.Find(m_strTextFilter)))
	{
		OutputDebugStr(_T("MessageBoxW Hook,") + strCaption + _T(",") + strText + _T("\n"));
		return 0;
	}
	return ((MYMESSAGEBOXW)m_OldMessageBoxW)(hWnd, lpText, lpCaption, uType);
}

void CMessageBoxFilter::SetEnable(BOOL bEnable/*=TRUE*/)
{
	m_bEnable = bEnable;
}

void CMessageBoxFilter::SetCaptionFilter(CString strSubstring)
{
	m_strCaptionFilter = strSubstring;
}

void CMessageBoxFilter::SetTextFilter(CString strSubstring)
{
	m_strTextFilter = strSubstring;
}

CMessageBoxFilter *CMessageBoxFilter::CreatInstance(void)
{
	if (NULL == m_pMessageBoxFilter)
	{
		m_pMessageBoxFilter = new CMessageBoxFilter;
	}
	return m_pMessageBoxFilter;
}
